home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsprefix / fsprefixOps.c < prev    next >
C/C++ Source or Header  |  1991-05-10  |  68KB  |  2,233 lines

  1. /* 
  2.  * fsPrefix.c --
  3.  *
  4.  *    Implementation of the prefix table.  The prefix table is used
  5.  *    to determine the server for a file depending on the
  6.  *    first part of the file's name.  Operations on pathnames get
  7.  *    passed through Fsprefix_LookupOperation (and Fsprefix_TwoNameOperation) that
  8.  *    handles the iteration over the prefix table that is due to redirections
  9.  *    from servers as a pathname wanders from domain to domain.  There
  10.  *    is also set of low-level procedures for direct operations on the prefix
  11.  *    table itself; add, delete, initialize, etc.
  12.  *
  13.  *    TODO: Extract the recovery related junk.  The prefix table is used
  14.  *    as a convenient place to record recovery state and synchronize
  15.  *    opens with re-opens, but the recov module's user-state flags should be
  16.  *    used instead.
  17.  *
  18.  * Copyright 1987 Regents of the University of California
  19.  * All rights reserved.
  20.  * Permission to use, copy, modify, and distribute this
  21.  * software and its documentation for any purpose and without
  22.  * fee is hereby granted, provided that the above copyright
  23.  * notice appear in all copies.  The University of California
  24.  * makes no representations about the suitability of this
  25.  * software for any purpose.  It is provided "as is" without
  26.  * express or implied warranty.
  27.  */
  28.  
  29. #ifndef lint
  30. static char rcsid[] = "$Header: /sprite/src/kernel/fsprefix/RCS/fsprefixOps.c,v 9.13 91/05/10 12:42:18 mgbaker Exp $ SPRITE (Berkeley)";
  31. #endif not lint
  32.  
  33.  
  34. #include <sprite.h>
  35. #include <fs.h>
  36. #include <fsprefix.h>
  37. #include <fsprefixInt.h>
  38. #include <fsNameOps.h>
  39. #include <fsutil.h>
  40. #include <fsutilTrace.h>
  41. #include <fsStat.h>
  42. #include <fsio.h>
  43. #include <vm.h>
  44. #include <rpc.h>
  45. #include <proc.h>
  46. #include <dbg.h>
  47. #include <string.h>
  48.  
  49. #ifdef SOSP91
  50. #include <sospRecord.h>
  51. #endif
  52.  
  53. #ifdef SOSP91
  54. int SOSPLookupNum = 0;        /* Number of name lookups. */
  55. int SOSPLookupComponent = 0;    /* Number of name components. */
  56. int SOSPLookupPrefixComponent = 0; /* Number of prefix components. */
  57. int SOSPLookupAbs = 0;        /* Number of absolute lookups. */
  58. #endif
  59.  
  60. static List_Links prefixListHeader;
  61. static List_Links *prefixList = &prefixListHeader;
  62.  
  63. static Sync_Lock prefixLock = Sync_LockInitStatic("Fs:prefixLock");
  64. #define LOCKPTR (&prefixLock)
  65.  
  66. /*
  67.  * Debuging variables.
  68.  */
  69. Boolean fsprefix_FileNameTrace = FALSE;
  70.  
  71. /*
  72.  * Forward references.
  73.  */
  74. static char *NameOp _ARGS_((int lookupOperation));
  75. static Fsprefix *PrefixInsert _ARGS_((char *prefix, int serverID, 
  76.         Fs_HandleHeader *hdrPtr, int domainType, int flags));
  77. static void PrefixUpdate _ARGS_((Fsprefix *prefixPtr, int serverID, 
  78.         Fs_HandleHeader *hdrPtr, int domainType, int flags));
  79. static ReturnStatus LocatePrefix _ARGS_((char *fileName, int serverID, 
  80.         int *domainTypePtr, Fs_HandleHeader **hdrPtrPtr));
  81. static ReturnStatus GetPrefix _ARGS_((char *fileName, Boolean follow, 
  82.         Fs_HandleHeader **hdrPtrPtr, Fs_FileID *rootIDPtr,
  83.         char **lookupNamePtr, int *domainTypePtr,
  84.         Fsprefix **prefixPtrPtr));
  85. static void GetNilPrefixes _ARGS_((List_Links *listPtr));
  86. static ReturnStatus DumpExportList _ARGS_((Fsprefix *prefixPtr, int size, 
  87.         char *buffer));
  88.  
  89.  
  90.  
  91. /*
  92.  *----------------------------------------------------------------------
  93.  *
  94.  * Fsprefix_LookupOperation --
  95.  *
  96.  *    This uses the prefix table to choose a server and domain-type for
  97.  *    a pathname lookup operation.  This is called by the routines in
  98.  *    fsNameOps.c to do opens, removes, mkdir, rmdir, etc. etc.  The
  99.  *    domain-type name lookup routines may return pathnames instead of
  100.  *    results    if the pathname left the domain of the server originally
  101.  *    chosen by the prefix table.  This routine handles these "re-directed"
  102.  *    pathnames and hides the iteration between the prefix table and
  103.  *    the various servers.
  104.  *
  105.  * Results:
  106.  *    The results of the lookup operation.
  107.  *
  108.  * Side effects:
  109.  *    This may fault new entries into the prefix table.
  110.  *
  111.  *----------------------------------------------------------------------
  112.  */
  113. ReturnStatus
  114. Fsprefix_LookupOperation(fileName, operation, follow, argsPtr, resultsPtr, nameInfoPtr)
  115.     char     *fileName;    /* File name to lookup */
  116.     int     operation;    /* Operation to perform on the file */
  117.     Boolean    follow;        /* TRUE if lookup will follow links.  FALSE
  118.                  * means we won't indirect via a prefix which
  119.                  * matches the name exactly. */
  120.     Address     argsPtr;    /* Operation specific arguments.  NOTE: it
  121.                  * is assumed that the first thing in the
  122.                  * arguments is a prefix file ID, except on
  123.                  * the IMPORT/EXPORT operations.  We set the
  124.                  * prefix fileID here as a convenience to
  125.                  * the name lookup routines we branch to. */
  126.     Address     resultsPtr;    /* Operation specific results */
  127.     Fs_NameInfo    *nameInfoPtr;    /* If non-NIL, set up to contain state needed
  128.                  * to get back to the name server.  This is
  129.                  * used with FS_DOMAIN_OPEN which passes
  130.                  * in the nameInfoPtr from the stream. */
  131. {
  132.     ReturnStatus     status;        /* General error code */
  133.     int         domainType;    /* Set from the prefix table lookup */
  134.     Fs_HandleHeader     *hdrPtr;    /* Set from the prefix table lookup */
  135.     char         *lookupName;    /* Returned from the prefix table 
  136.                      * lookup */
  137.     Fs_RedirectInfo     *redirectInfoPtr;/* Returned from servers if their
  138.                      * lookup leaves their domain */
  139.     Fs_RedirectInfo     *oldInfoPtr;    /* Needed to free up the new name
  140.                      * buffer allocated by the domain
  141.                      * lookup routine. */
  142.     Fs_FileID        rootID;        /* ID of domain root */
  143.     Fsprefix         *prefixPtr;    /* Returned from prefix table lookup 
  144.                      * and saved in the file handle */
  145.     int         numRedirects = 0;/* Number of iterations between 
  146.                       * servers. This is used to catch the 
  147.                       * looping occurs with absolute links
  148.                       * that are circular. */
  149.  
  150.     redirectInfoPtr = (Fs_RedirectInfo *) NIL;
  151.     oldInfoPtr = (Fs_RedirectInfo *) NIL;
  152.  
  153.     if (sys_ShuttingDown) {
  154.     /*
  155.      * Lock processes out of the filesystem during a shutdown.
  156.      */
  157.     return(FAILURE);
  158.     }
  159.     do {
  160.     status = GetPrefix(fileName, follow, &hdrPtr, &rootID, &lookupName,
  161.                 &domainType, &prefixPtr);
  162.     if (status == SUCCESS) {
  163.         switch(operation) {
  164.         case FS_DOMAIN_IMPORT:
  165.         case FS_DOMAIN_EXPORT:
  166.             break;
  167.         case FS_DOMAIN_OPEN:
  168.             FSUTIL_TRACE_NAME(FSUTIL_TRACE_LOOKUP_START, lookupName);
  169.             /* Fall Through */
  170.         default: {
  171.             /*
  172.              * It is assumed that the first part of the bundled
  173.              * arguments are the prefix fileID, which indicates the
  174.              * start of the lookup, and the prefix rootID, which
  175.              * indicates the top of the domain.
  176.              */
  177.             register Fs_LookupArgs *lookupArgsPtr =
  178.                 (Fs_LookupArgs *)argsPtr;
  179.             lookupArgsPtr->prefixID = hdrPtr->fileID;
  180.             lookupArgsPtr->rootID = rootID;
  181.             break;
  182.         }
  183.         }
  184.         /*
  185.          * Fork out to the domain lookup operation.
  186.          */
  187.         status = (*fs_DomainLookup[domainType][operation])
  188.            (hdrPtr, lookupName, argsPtr, resultsPtr, &redirectInfoPtr);
  189.         if (fsprefix_FileNameTrace) {
  190.         printf("\treturns <%x>\n", status);
  191.         }
  192.         switch (status) {
  193.             case FS_LOOKUP_REDIRECT: {
  194.             /*
  195.              * Lookup left the domain of the server chosen on the
  196.              * basis of the prefix table.  Generate an absolute name
  197.              * from the one returned by the server and loop back to
  198.              * the prefix table lookup.  We are careful to save a
  199.              * pointer to the redirect info because it contains the
  200.              * current pathname.  We also free any redirect info
  201.              * from previous iterations to prevent a core leak.
  202.              */
  203.             fs_Stats.prefix.redirects++; numRedirects++;
  204.             if (numRedirects > FS_MAX_LINKS) {
  205.             status = FS_NAME_LOOP;
  206.             fs_Stats.prefix.loops++;
  207.             } else {
  208.             status = FsprefixLookupRedirect(redirectInfoPtr, prefixPtr,
  209.                                   &fileName);
  210.             if (oldInfoPtr != (Fs_RedirectInfo *)NIL) {
  211.                 free((Address)oldInfoPtr);
  212.             }
  213.             oldInfoPtr = redirectInfoPtr;
  214.             redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  215.             }
  216.             break;
  217.         }
  218.             case SUCCESS: {
  219.             if (nameInfoPtr != (Fs_NameInfo *)NIL) {
  220.             /*
  221.              * Set up the name info for the file.  The back pointer
  222.              * to the prefix table is used by us later to handle
  223.              * re-directs.  The rootID is noted here and passed
  224.              * to the server during relative lookups to trap
  225.              * ascending off the root of a domain via "..".
  226.              * The fileID is used by the attributes routines to get
  227.              * to the name server for open streams.
  228.              */
  229.             nameInfoPtr->fileID =
  230.                 ((Fs_OpenResults *)resultsPtr)->nameID;
  231.             nameInfoPtr->rootID = rootID;
  232.             nameInfoPtr->domainType = domainType;
  233.             nameInfoPtr->prefixPtr = prefixPtr;
  234.             }
  235.             break;
  236.         }
  237.         case RPC_TIMEOUT:
  238.         case RPC_SERVICE_DISABLED:
  239.         case FS_STALE_HANDLE: {
  240.             /*
  241.              * Block waiting for regular recovery of the prefix handle.
  242.              */
  243.             if (status == FS_STALE_HANDLE) {
  244.             fs_Stats.prefix.stale++;
  245.             } else {
  246.             fs_Stats.prefix.timeouts++;
  247.             }
  248.             Fsutil_WantRecovery(hdrPtr);
  249.             printf("%s of \"%s\" waiting for recovery\n",
  250.                 NameOp(operation), fileName);
  251.             status = Fsutil_WaitForRecovery(hdrPtr, status);
  252.             if (status == SUCCESS) {
  253.             /*
  254.              * Successfully waited for the server to reboot.
  255.              * Set the status to redirect so we go around the
  256.              * loop again.
  257.              */
  258.             status = FS_LOOKUP_REDIRECT;
  259.             } else if ((status != GEN_ABORTED_BY_SIGNAL) &&
  260.                        (fileName[0] == '/')) {
  261.             /*
  262.              * Recovery failed, so we clear handle of the prefix
  263.              * used to get to the server and try again in case
  264.              * the prefix is served elsewhere.
  265.              */
  266.             Fsprefix_HandleClose(prefixPtr, FSPREFIX_IMPORTED);
  267.             status = FS_LOOKUP_REDIRECT;
  268.             }
  269.             break;
  270.         }
  271.         default:
  272.             break;
  273.         }
  274.     }
  275.     } while (status == FS_LOOKUP_REDIRECT);
  276.     if (oldInfoPtr != (Fs_RedirectInfo *)NIL) {
  277.     free((Address) oldInfoPtr);
  278.     }
  279.  
  280.     return(status);
  281. }
  282.  
  283. /*
  284.  *----------------------------------------------------------------------
  285.  *
  286.  * Fsprefix_TwoNameOperation --
  287.  *
  288.  *    This is a version of Fsprefix_LookupOperation that deals with two
  289.  *    pathnames.  The operation, either Rename or HardLink, will only
  290.  *    be attempted if the two pathnames are part of the same domain.
  291.  *    Two pathnames are determined to be in the same domain in part
  292.  *    by the domain specific lookup routine, and in part by us in
  293.  *    the following way.  The standard iteration over prefix table
  294.  *    for the first pathname (the already existing file) is done,
  295.  *    and the prefix info and relative name for it are passed to
  296.  *    the domain specific procedure along with our first guess as
  297.  *    to the domain and relative name of the second pathname.  The
  298.  *    domain specific procedure will abort with a CROSS_DOMAIN error
  299.  *    if it thinks the second pathname is served elsewhere.  In this case
  300.  *    this procedure has to verify that by getting the attributes of
  301.  *    the parent directory of the second name.  This may cause more
  302.  *    iteration over the prefix table to get the final prefix info
  303.  *    and relative name for the second name.  At that point we can
  304.  *    finally determine if the pathnames are in the same domain.
  305.  *
  306.  * Results:
  307.  *    The results of the two pathname operation.
  308.  *
  309.  * Side effects:
  310.  *    This may fault new entries into the prefix table.
  311.  *
  312.  *----------------------------------------------------------------------
  313.  */
  314. ReturnStatus
  315. Fsprefix_TwoNameOperation(operation, srcName, dstName, lookupArgsPtr)
  316.     int            operation;   /* FS_DOMAIN_RENAME, FS_DOMAIN_HARD_LINK */
  317.     char        *srcName;    /* Name of existing file */
  318.     char        *dstName;     /* New name, or link name */
  319.     Fs_LookupArgs    *lookupArgsPtr; /* ID information */
  320. {
  321.     ReturnStatus    status;        /* General error code */
  322.     int            srcDomain;    /* Domain type of srcName */
  323.     int         dstDomain;
  324.     Fs_HandleHeader    *srcHdrPtr;    /* Prefix handle of srcName */
  325.     Fs_HandleHeader     *dstHdrPtr;
  326.     char        *srcLookupName;    /* Relative version of srcName */
  327.     char         *dstLookupName;
  328.     Fsprefix        *srcPrefixPtr;    /* Prefix entry for srcName */
  329.     Fsprefix         *dstPrefixPtr;
  330.     Fs_FileID        srcRootID;    /* ID of srcName domain root */
  331.     Fs_FileID        dstRootID;
  332.     int            numRedirects;    /* To detect loops in directories */
  333.     Boolean        srcNameError;    /* TRUE if redirect info or stale
  334.                      * handle error applies to srcName,
  335.                      * FALSE if it applies to dstName. */
  336.     /*
  337.      * The domain-lookup routine allocates a buffer for a redirected pathname.
  338.      * FsprefixLookupRedirect() subsequently generates a new absolute pathname
  339.      * in this buffer.  We have to carefully hold onto this buffer during
  340.      * the next iteration of the lookup loop, and still be able to free
  341.      * it later to avoid core leaks.  The 'src' and 'dst' buffers are
  342.      * used for this reason.
  343.      */
  344.     Fs_RedirectInfo    *redirectInfoPtr = (Fs_RedirectInfo *) NIL;
  345.     Fs_RedirectInfo    *srcRedirectPtr = (Fs_RedirectInfo *) NIL;
  346.     Fs_RedirectInfo    *dstRedirectPtr = (Fs_RedirectInfo *) NIL;
  347.  
  348.     if (sys_ShuttingDown) {
  349.     /*
  350.      * Lock processes out of the filesystem during a shutdown.
  351.      */
  352.     return(FAILURE);
  353.     }
  354.     numRedirects = 0;
  355. getSrcPrefix:
  356.     status = GetPrefix(srcName, 0, &srcHdrPtr, &srcRootID, &srcLookupName,
  357.                     &srcDomain, &srcPrefixPtr);
  358.     if (status != SUCCESS) {
  359.     goto exit;
  360.     }
  361.     lookupArgsPtr->prefixID = srcHdrPtr->fileID;
  362.     lookupArgsPtr->rootID = srcRootID;
  363. getDstPrefix:
  364.     status = GetPrefix(dstName, 0, &dstHdrPtr, &dstRootID, &dstLookupName,
  365.                     &dstDomain, &dstPrefixPtr);
  366.     if (status != SUCCESS) {
  367.     goto exit;
  368.     }
  369. retry:
  370.     status = (*fs_DomainLookup[srcDomain][operation])
  371.        (srcHdrPtr, srcLookupName, dstHdrPtr, dstLookupName, lookupArgsPtr,
  372.             &redirectInfoPtr, &srcNameError);
  373.     if (fsprefix_FileNameTrace) {
  374.     printf("\treturns <%x>\n", status);
  375.     }
  376.     switch(status) {
  377.     case RPC_SERVICE_DISABLED:
  378.     case RPC_TIMEOUT:
  379.         srcNameError = TRUE;
  380.         /*
  381.          * FALL THROUGH to regular recovery.
  382.          */
  383.     case FS_STALE_HANDLE: {
  384.         Fs_HandleHeader *staleHdrPtr;
  385.         staleHdrPtr = (srcNameError ? srcHdrPtr : dstHdrPtr);
  386.         Fsutil_WantRecovery(staleHdrPtr);
  387.         printf("%s of \"%s\" and \"%s\" waiting for recovery\n",
  388.                 NameOp(operation), srcName, dstName);
  389.         status = Fsutil_WaitForRecovery(staleHdrPtr, status);
  390.         if (status == SUCCESS) {
  391.         goto retry;
  392.         } else if (status != GEN_ABORTED_BY_SIGNAL) {
  393.         /*
  394.          * Recovery failed.  On absolute paths clear handle of the
  395.          * prefix used to get to the server and try again.
  396.          */
  397.         if ((srcNameError) && (srcName[0] == '/')) {
  398.             Fsprefix_HandleClose(srcPrefixPtr, FSPREFIX_IMPORTED);
  399.             status = FS_LOOKUP_REDIRECT;
  400.         } else if ((!srcNameError) && (dstName[0] == '/')) {
  401.             Fsprefix_HandleClose(dstPrefixPtr, FSPREFIX_IMPORTED);
  402.             status = FS_LOOKUP_REDIRECT;
  403.         }
  404.         }
  405.         break;
  406.     }
  407.     case FS_LOOKUP_REDIRECT:
  408.         /*
  409.          * The pathname left the server's domain, and it has returned
  410.          * us a new name.  We generate a new absolute pathname and
  411.          * save the pointer to the buffer.  It is now safe to free
  412.          * the buffer used during the last iteration as well.
  413.          */
  414.         fs_Stats.prefix.redirects++;
  415.         numRedirects++;
  416.         if (numRedirects > FS_MAX_LINKS) {
  417.         status = FS_NAME_LOOP;
  418.         fs_Stats.prefix.loops++;
  419.         } else if (srcNameError) {
  420.         status = FsprefixLookupRedirect(redirectInfoPtr, srcPrefixPtr,
  421.                       &srcName);
  422.         if (srcRedirectPtr != (Fs_RedirectInfo *)NIL) {
  423.             free((Address)srcRedirectPtr);
  424.         }
  425.         srcRedirectPtr = redirectInfoPtr;
  426.         redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  427.         } else {
  428.         status = FsprefixLookupRedirect(redirectInfoPtr, dstPrefixPtr,
  429.                       &dstName);
  430.         if (dstRedirectPtr != (Fs_RedirectInfo *)NIL) {
  431.             free((Address)dstRedirectPtr);
  432.         }
  433.         dstRedirectPtr = redirectInfoPtr;
  434.         redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  435.         }
  436.         break;
  437.     case FS_CROSS_DOMAIN_OPERATION: {
  438.         /*
  439.          * The server thinks the second name is not served by it.
  440.          * Here we attempt to get the attributes of the second name
  441.          * in order to bounce through links and end up with a good prefix.
  442.          */
  443.         ReturnStatus    status2;
  444.         Fs_OpenArgs        openArgs;
  445.         Fs_GetAttrResults    getAttrResults;
  446.         Fs_Attributes    dstAttr;    /* Attrs of destination */
  447.         Fs_FileID        dstFileID;
  448.  
  449.         openArgs.useFlags = FS_FOLLOW;
  450.         openArgs.permissions = 0;
  451.         openArgs.type = FS_FILE;
  452.         openArgs.clientID = rpc_SpriteID;
  453.         Fs_SetIDs((Proc_ControlBlock *)NIL, &openArgs.id);
  454.  
  455.         openArgs.prefixID = dstHdrPtr->fileID;
  456.         openArgs.rootID = dstRootID;
  457.  
  458.         getAttrResults.attrPtr = &dstAttr;
  459.         getAttrResults.fileIDPtr = &dstFileID;
  460. getAttr:
  461.         status2 = (*fs_DomainLookup[dstDomain][FS_DOMAIN_GET_ATTR])
  462.             (dstHdrPtr, dstLookupName, (Address)&openArgs,
  463.             (Address)&getAttrResults, &redirectInfoPtr);
  464.         switch(status2) {
  465.         default:
  466.             if (dstRootID.serverID != srcRootID.serverID ||
  467.             dstRootID.major != srcRootID.major) {
  468.             /*
  469.              * Really is a cross-domain operation.
  470.              */
  471.             status = FS_CROSS_DOMAIN_OPERATION;
  472.             break;
  473.             } else {
  474.             goto retry;
  475.             }
  476.         case FS_LOOKUP_REDIRECT: {
  477.             fs_Stats.prefix.redirects++;
  478.             numRedirects++;
  479.             if (numRedirects > FS_MAX_LINKS) {
  480.             status = FS_NAME_LOOP;
  481.             fs_Stats.prefix.loops++;
  482.             } else {
  483.             status = FsprefixLookupRedirect(redirectInfoPtr, dstPrefixPtr,
  484.                           &dstName);
  485.             if (dstRedirectPtr != (Fs_RedirectInfo *)NIL) {
  486.                 free((Address)dstRedirectPtr);
  487.             }
  488.             dstRedirectPtr = redirectInfoPtr;
  489.             redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  490.             srcNameError = FALSE;
  491.             /*
  492.              * Will fall out and then zip up to getDstPrefix.
  493.              */
  494.             }
  495.             break;
  496.         }
  497.         case RPC_SERVICE_DISABLED:
  498.         case RPC_TIMEOUT:
  499.         case FS_STALE_HANDLE: {
  500.             Fsutil_WantRecovery(dstHdrPtr);
  501.             printf("Get Attr of \"%s\" waiting for recovery\n",
  502.                      dstName);
  503.             status2 = Fsutil_WaitForRecovery(dstHdrPtr, status2);
  504.             if (status2 == SUCCESS) {
  505.             goto getAttr;
  506.             } else if ((status != GEN_ABORTED_BY_SIGNAL) &&
  507.                        (dstName[0] == '/')) {
  508.             Fsprefix_HandleClose(dstPrefixPtr, FSPREFIX_IMPORTED);
  509.             status = FS_LOOKUP_REDIRECT;
  510.             srcNameError = FALSE;
  511.             }
  512.             break;
  513.         }
  514.         }
  515.         break;
  516.     }
  517.     default:
  518.         /*
  519.          * SUCCESS or simple lookup failure.
  520.          */
  521.         break;
  522.     }
  523.     if (status == FS_LOOKUP_REDIRECT) {
  524.     if (srcNameError) {
  525.         goto getSrcPrefix;
  526.     } else {
  527.         goto getDstPrefix;
  528.     }
  529.     }
  530. exit:
  531.     if (srcRedirectPtr != (Fs_RedirectInfo *)NIL) {
  532.     free((Address)srcRedirectPtr);
  533.     }
  534.     if (dstRedirectPtr != (Fs_RedirectInfo *)NIL) {
  535.     free((Address)dstRedirectPtr);
  536.     }
  537.     return(status);
  538. }
  539.  
  540. /*
  541.  *----------------------------------------------------------------------
  542.  *
  543.  * FsprefixLookupRedirect --
  544.  *
  545.  *    Process a filename returned from a server after the lookup left
  546.  *    the server's domain.  This takes any prefix information and adds
  547.  *    to new entries to the prefix table, then it recomputes a new filename
  548.  *    and returns that so the caller can re-iterate the lookup.
  549.  *
  550.  * Results:
  551.  *    A return status, and a new file name.
  552.  *
  553.  * Side effects:
  554.  *    If the server tells us about a prefix it gets added to the
  555.  *    prefix table, but with no token or domain type.
  556.  *
  557.  *----------------------------------------------------------------------
  558.  */
  559. ReturnStatus
  560. FsprefixLookupRedirect(redirectInfoPtr, prefixPtr, fileNamePtr)
  561.     Fs_RedirectInfo    *redirectInfoPtr;/* New name and prefix from server */
  562.     Fsprefix        *prefixPtr;    /* Prefix table entry used to select
  563.                      * the server. */
  564.     char **fileNamePtr;            /* Return, new name to lookup. This is a
  565.                      * pointer into the fileName buffer of
  566.                      * *redirectInfoPtr.  This means that the
  567.                      * caller has to be careful and not
  568.                      * reference *fileNamePtr after it calls
  569.                      * the domain lookup routine which will
  570.                      * overwrite *redirectInfoPtr */
  571. {
  572.     register char *prefix;
  573.  
  574.     if (fsprefix_FileNameTrace) {
  575.     printf("FsRedirect: \"%s\" (%d)\n", redirectInfoPtr->fileName,
  576.                 redirectInfoPtr->prefixLength);
  577.     }
  578.     if (redirectInfoPtr->prefixLength > 0) {
  579.     /*
  580.      * We are being told about a new prefix after the server
  581.      * hit a remote link.  The prefix is embedded in the
  582.      * beginning of the returned complete pathname.
  583.      */
  584.     prefix = (char *)malloc(redirectInfoPtr->prefixLength + 1);
  585.     (void)strncpy(prefix, redirectInfoPtr->fileName,
  586.             redirectInfoPtr->prefixLength);
  587.     prefix[redirectInfoPtr->prefixLength] = '\0';
  588.     Fsprefix_Load(prefix, RPC_BROADCAST_SERVER_ID, FSPREFIX_IMPORTED);
  589.     free((Address) prefix);
  590.     }
  591.     if (redirectInfoPtr->fileName[0] == '.' &&
  592.     redirectInfoPtr->fileName[1] == '.') {
  593.     register int i;
  594.     register int preLen;
  595.     register char *fileName;
  596.     /*
  597.      * The server ran off the top of its domain.  Compute a new name
  598.      * from the prefix for the domain and the relative name returned.
  599.      * Again, we use the redirectInfoPtr buffer to construct the new
  600.      * name so we have to be careful not to use fileName after the
  601.      * domain lookup routine returns.  At this point
  602.      * prefix = "/pre/fix"
  603.      * fileName = "../rest/of/path"
  604.      * and we need
  605.      * fileName = "/pre/rest/of/path"
  606.      */
  607.     prefix = prefixPtr->prefix;
  608.     fileName = redirectInfoPtr->fileName;
  609.     preLen = strlen(prefix);
  610.     /*
  611.      * Scan the prefix from the right end for the first '/'
  612.      */
  613.     for (i = preLen-1; i >= 0 ; i--) {
  614.         if (prefix[i] == '/') {
  615.         break;
  616.         }
  617.     }
  618.     preLen = i+1;
  619.     if (preLen == 1) {
  620.         /*
  621.          * Have to shift the name to the left, up against the beginning /
  622.          */
  623.         for (i=3; ; i++) {
  624.         fileName[i-2] = fileName[i];
  625.         if (fileName[i] == '\0') {
  626.             break;
  627.         }
  628.         }
  629.     } else {
  630.         /*
  631.          * Shift the fileName over to the right so the beginning of the
  632.          * prefix can be inserted before it.  The magic 2 refers to the
  633.          * length of ".."
  634.          */
  635.         for (i = strlen(fileName); i >= 2; i--) {
  636.         fileName[i + preLen - 2] = fileName[i];
  637.         }
  638.     }
  639.     /*
  640.      * Insert the prefix.
  641.      */
  642.     for (i = 0 ; i < preLen ; i++) {
  643.         fileName[i] = prefix[i];
  644.     }
  645.     }
  646.     if (redirectInfoPtr->fileName[0] == '/') {
  647.     /*
  648.      * Either just computed a new pathname or the server returned
  649.      * an absolute name to us.
  650.      */
  651.     *fileNamePtr = redirectInfoPtr->fileName;
  652.     return(FS_LOOKUP_REDIRECT);
  653.     } else {
  654.     printf(
  655.       "Fsprefix_LookupOperation: Bad format of returned file name \"%s\".\n",
  656.       redirectInfoPtr->fileName);
  657.     return(FAILURE);
  658.     }
  659. }
  660.  
  661. /*
  662.  *----------------------------------------------------------------------
  663.  *
  664.  * NameOp --
  665.  *
  666.  *    Return a string for a name operation.
  667.  *
  668.  * Results:
  669.  *    None.
  670.  *
  671.  * Side effects:
  672.  *    Set up the list links.
  673.  *
  674.  *----------------------------------------------------------------------
  675.  */
  676. static char *
  677. NameOp(lookupOperation)
  678.     int lookupOperation;
  679. {
  680.     switch(lookupOperation) {
  681.     case FS_DOMAIN_IMPORT:
  682.         return("import");
  683.     case FS_DOMAIN_EXPORT:
  684.         return("export");
  685.     case FS_DOMAIN_OPEN:
  686.         return("open");
  687.     case FS_DOMAIN_GET_ATTR:
  688.         return("get attr");
  689.     case FS_DOMAIN_SET_ATTR:
  690.         return("set attr");
  691.     case FS_DOMAIN_MAKE_DEVICE:
  692.         return("make device");
  693.     case FS_DOMAIN_MAKE_DIR:
  694.         return("make directory");
  695.     case FS_DOMAIN_REMOVE:
  696.         return("remove");
  697.     case FS_DOMAIN_REMOVE_DIR:
  698.         return("remove directory");
  699.     case FS_DOMAIN_RENAME:
  700.         return("rename");
  701.     case FS_DOMAIN_HARD_LINK:
  702.         return("link");
  703.     default:
  704.         return("(unknown lookup operation)");
  705.     }
  706. }
  707.  
  708. /*
  709.  *----------------------------------------------------------------------
  710.  *
  711.  * Fsprefix_Init --
  712.  *
  713.  *    Initialize the prefix table.
  714.  *
  715.  * Results:
  716.  *    None.
  717.  *
  718.  * Side effects:
  719.  *    Set up the list links.
  720.  *
  721.  *----------------------------------------------------------------------
  722.  */
  723. void
  724. Fsprefix_Init()
  725. {
  726.     List_Init(prefixList);
  727. }
  728.  
  729. /*
  730.  *----------------------------------------------------------------------
  731.  *
  732.  * Fsprefix_Install --
  733.  *
  734.  *    Add an entry to the prefix table.
  735.  *
  736.  * Results:
  737.  *    A pointer to the prefix table entry.
  738.  *
  739.  * Side effects:
  740.  *    Add an entry to the prefix table.
  741.  *
  742.  *----------------------------------------------------------------------
  743.  */
  744. ENTRY Fsprefix *
  745. Fsprefix_Install(prefix, hdrPtr, domainType, flags)
  746.     char        *prefix;    /* String to install as a prefix */
  747.     Fs_HandleHeader    *hdrPtr;    /* Handle from server of the prefix */
  748.     int            domainType;    /* Default domain type for prefix. */
  749.     int            flags;    /* FSPREFIX_EXPORTED | FSPREFIX_IMPORTED. */
  750. {
  751.     register Fsprefix *prefixPtr;
  752.  
  753.     LOCK_MONITOR;
  754.  
  755.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  756.     if (strcmp(prefixPtr->prefix, prefix) == 0) {
  757.         /*
  758.          * Update information in the table.
  759.          */
  760.         PrefixUpdate(prefixPtr, FS_NO_SERVER, hdrPtr, domainType, flags);
  761.         UNLOCK_MONITOR;
  762.         return(prefixPtr);
  763.     }
  764.     }
  765.     prefixPtr = PrefixInsert(prefix, FS_NO_SERVER, hdrPtr, domainType, flags);
  766.     UNLOCK_MONITOR;
  767.     return(prefixPtr);
  768. }
  769.  
  770. /*
  771.  *----------------------------------------------------------------------
  772.  *
  773.  * Fsprefix_Load --
  774.  *
  775.  *    Force a prefix to occur in the prefix table.  This is needed because
  776.  *    the Unix Domain server does not do REDIRECTS right so we have
  777.  *    no other way to forcibly load a prefix.
  778.  *
  779.  * Results:
  780.  *    None.
  781.  *
  782.  * Side effects:
  783.  *    Add an entry to the prefix table.  
  784.  *
  785.  *----------------------------------------------------------------------
  786.  */
  787. ENTRY void
  788. Fsprefix_Load(prefix, serverID, flags)
  789.     char *prefix;        /* String to install as a prefix */
  790.     int  serverID;        /* Id of server for prefix */
  791.     int flags;            /* Prefix flags from fsPrefix.h */
  792. {
  793.     register Fsprefix *prefixPtr;
  794.  
  795.     LOCK_MONITOR;
  796.  
  797.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  798.     if (strcmp(prefixPtr->prefix, prefix) == 0) {
  799.         /*
  800.          * Update information in the table.
  801.          */
  802.         PrefixUpdate(prefixPtr, serverID, (Fs_HandleHeader *)NIL, -1, 
  803.         flags);    
  804.         UNLOCK_MONITOR;
  805.         return;
  806.     }
  807.     }
  808.     /*
  809.      * Add new entry to the table.
  810.      */
  811.     (void)PrefixInsert(prefix, serverID, (Fs_HandleHeader *)NIL, -1,
  812.             flags);
  813.     UNLOCK_MONITOR;
  814.     return;
  815. }
  816.  
  817. /*
  818.  *----------------------------------------------------------------------
  819.  *
  820.  * PrefixInsert --
  821.  *
  822.  *    Insert an entry into the prefix table. If the hdtPtr is not
  823.  *    NIL then the serverID it contains is used, otherwise the
  824.  *    serverID parameter is used.
  825.  *
  826.  * Results:
  827.  *    None.
  828.  *
  829.  * Side effects:
  830.  *    Sets the hdrPtr, etc. of the prefix.  Also resets number of
  831.  *    active opens/delay opens state for the prefix.
  832.  *
  833.  *----------------------------------------------------------------------
  834.  */
  835. static INTERNAL Fsprefix *
  836. PrefixInsert(prefix, serverID, hdrPtr, domainType, flags)
  837.     char        *prefix;    /* The prefix itself */
  838.     int            serverID;    /* Id of server for prefix */
  839.     Fs_HandleHeader    *hdrPtr;    /* Handle for the prefix from server */
  840.     int            domainType;    /* Domain type of handle */
  841.     int            flags;        /* import, export, etc. */
  842. {
  843.     register Fsprefix *prefixPtr;
  844.     register char *prefixCopy;
  845.  
  846.     prefixPtr = (Fsprefix *)malloc(sizeof(Fsprefix));
  847.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  848.     prefixPtr->serverID    = hdrPtr->fileID.serverID;
  849.     } else {
  850.     prefixPtr->serverID    = serverID;
  851.     }
  852.     prefixPtr->prefixLength    = strlen(prefix);
  853.     prefixCopy            = (char *)malloc(prefixPtr->prefixLength+1);
  854.     (void)strcpy(prefixCopy, prefix);
  855.     prefixPtr->prefix        = prefixCopy;
  856.     prefixPtr->hdrPtr        = hdrPtr;
  857.     prefixPtr->domainType    = domainType;
  858.     prefixPtr->flags        = flags;
  859.     prefixPtr->activeOpens    = 0;
  860.     prefixPtr->delayOpens    = FALSE;
  861.     List_Init(&prefixPtr->exportList);
  862.  
  863.     /*
  864.      * At this point one could think about sorting the prefix table
  865.      * in some way.  However, for now we just add new prefixes
  866.      * to the end.  The PrefixLookup look scans the whole list anyway.
  867.      * Finally, there is a silly dependency on the ordering from
  868.      * the use of a prefix table entry to block OPENS during recovery.
  869.      * The first prefix that is controlled by a particular server is
  870.      * used to synchronize OPENS and REOPENS.  If this stupid
  871.      * dependency were removed (by using a different data
  872.      * structure, please, than the prefix table (I did all this to
  873.      * myself - my thanks to whoever fixes it)) then the prefix
  874.      * table could be sorted in order of increasing prefix length
  875.      * so that the prefix table scan could halt at the first non
  876.      * matching prefix.
  877.      */
  878.     List_Insert((List_Links *)prefixPtr, LIST_ATREAR(prefixList));
  879.     return(prefixPtr);
  880. }
  881.  
  882. /*
  883.  *----------------------------------------------------------------------
  884.  *
  885.  * PrefixUpdate --
  886.  *
  887.  *    Update a prefix table entry.  This is called in several cases:
  888.  *    during lookup redirection (via Fs_PrefixLoad), when exporting
  889.  *    a local domain as part of bootstrap, and when setting up the
  890.  *    serverID for domains not reachable by broadcast.  Basically,
  891.  *    if there is no handle associated with the prefix then the
  892.  *    handle that was passed in is installed.  Otherwise, we let
  893.  *    the flags change in order to export an existing entry, and
  894.  *    we let the serverID field be set in order to by-pass broadcast.
  895.  *
  896.  * Results:
  897.  *    None.
  898.  *
  899.  * Side effects:
  900.  *    Reinitializes the hdrPtr, etc. of the prefix.  Also resets number of
  901.  *    active opens/delay opens state for the prefix.
  902.  *
  903.  *----------------------------------------------------------------------
  904.  */
  905. static INTERNAL void
  906. PrefixUpdate(prefixPtr, serverID, hdrPtr, domainType, flags)
  907.     Fsprefix        *prefixPtr;    /* Table entry to update */
  908.     int            serverID;    /* Id of server for prefix */
  909.     Fs_HandleHeader    *hdrPtr;    /* Handle for the prefix from server */
  910.     int            domainType;    /* Domain type of handle */
  911.     int            flags;        /* import, export, etc. */
  912. {
  913.     if (prefixPtr->hdrPtr == (Fs_HandleHeader *)NIL) {
  914.     /*
  915.      * No handle, we are being updated during a pathname redirection.
  916.      */
  917.     prefixPtr->hdrPtr    = hdrPtr;
  918.     prefixPtr->domainType    = domainType;
  919.     prefixPtr->delayOpens    = FALSE;
  920.     prefixPtr->activeOpens    = 0;
  921.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  922.         prefixPtr->serverID = hdrPtr->fileID.serverID;
  923.     }
  924.     if (prefixPtr->flags & FSPREFIX_REMOTE) {
  925.         /*
  926.          * Save hard-wired information about the server location.
  927.          * Can only reset that info via Fsprefix_Clear.
  928.          */
  929.         flags |= FSPREFIX_REMOTE;
  930.     } else if ((hdrPtr == (Fs_HandleHeader *)NIL) &&
  931.            (prefixPtr->hdrPtr == (Fs_HandleHeader *)NIL)) {
  932.         /*
  933.          * No handle on prefix, no input handle.  Cache the input
  934.          * serverID and we'll contact it to establish
  935.          * the prefix handle.  At this point either serverID is the
  936.          * broadcast address, or serverID has a specific value and
  937.          * the FSREMOTE_PREFIX flag is set.
  938.          */
  939.         prefixPtr->serverID = serverID;
  940.     }
  941.     prefixPtr->flags    = flags & ~FSPREFIX_OVERRIDE;
  942.     } else {
  943.     /*
  944.      * Verify the new flags for the prefix table entry.
  945.      */
  946.     if (flags & FS_EXPORTED_PREFIX) {
  947.         /*
  948.          * A local prefix is being exported.  This happens during bootstrap.
  949.          */
  950.         prefixPtr->flags    |= FS_EXPORTED_PREFIX;
  951.     }
  952.     }
  953.     return;
  954. }
  955.  
  956. /*
  957.  *----------------------------------------------------------------------
  958.  *
  959.  * Fsprefix_Lookup --
  960.  *
  961.  *    Find an entry in the prefix table.  It is the caller's responsibility
  962.  *    to broadcast to get the handle for the prefix, if necessary.
  963.  *
  964.  * Results:
  965.  *    SUCCESS means there was a prefix match.  Still, *hdrPtr and
  966.  *    *domainTypePtr may be NIL to indicate that they are not
  967.  *    instantiated.
  968.  *
  969.  * Side effects:
  970.  *    None.
  971.  *
  972.  *----------------------------------------------------------------------
  973.  */
  974. ENTRY ReturnStatus
  975. Fsprefix_Lookup(fileName, flags, clientID, hdrPtrPtr, rootIDPtr, lookupNamePtr, 
  976.         serverIDPtr, domainTypePtr, prefixPtrPtr)
  977.     register char *fileName;    /* File name to match against */
  978.     int     flags;        /* FSPREFIX_IMPORTED | FSPREFIX_EXACT and
  979.                  * one of FSPREFIX_EXPORTED|FSPREFIX_LOCAL */
  980.     int        clientID;    /* Use to check export list */
  981.     Fs_HandleHeader **hdrPtrPtr;    /* Return, the handle for the prefix.  This is
  982.                  * NOT LOCKED and has no extra references. */
  983.     Fs_FileID    *rootIDPtr;    /* Return, ID of the root of the domain */
  984.     char     **lookupNamePtr;/* Return, If FS_NO_HANDLE this is the prefix
  985.                  * itself.  If SUCCESS, this is the relative
  986.                  * name after the prefix */
  987.     int        *serverIDPtr;    /* Return, If FS_NO_HANDLE this is the id
  988.                  * of the server for the prefix */
  989.     int        *domainTypePtr;    /* Return, the domain of the prefix */
  990.     Fsprefix    **prefixPtrPtr;    /* Return, prefix used to find the file */
  991. {
  992.     register Fs_ProcessState    *fsPtr;               /* For this process, to
  993.                              * return working dir.*/
  994.     register Fsprefix         *longestPrefixPtr;  /* Longest match */
  995.     register Fsprefix        *prefixPtr;        /* Pointer to table entry */
  996.     register Fs_NameInfo        *nameInfoPtr;        /* Name info for prefix */
  997.     ReturnStatus        status = SUCCESS;   /* Return value */
  998.     Boolean            exactMatch;        /* TRUE the fileName has
  999.                              * to match the prefix in 
  1000.                              * the table exactly */
  1001.     Boolean            wantLink;        /* TRUE if caller wants to
  1002.                              * inhibit indirection via
  1003.                              * a prefix so it can lstat
  1004.                              * the link file itself. */
  1005.  
  1006.     LOCK_MONITOR;
  1007.  
  1008.     longestPrefixPtr = (Fsprefix *) NIL;
  1009.     exactMatch = (flags & FSPREFIX_EXACT);
  1010.     wantLink = (flags & FSPREFIX_LINK_NOT_PREFIX);
  1011.     flags &= ~(FSPREFIX_EXACT|FSPREFIX_LINK_NOT_PREFIX);
  1012.     if (fileName[0] != '/') {
  1013.     /*
  1014.      * For relative names just return the handle from the current
  1015.      * working directory.  Also, don't accept relative names with
  1016.      * exact matches - that happens occasionally in error conditions.
  1017.      */
  1018.     fs_Stats.prefix.relative++;
  1019.     fsPtr = (Proc_GetEffectiveProc())->fsPtr;
  1020.     if (!exactMatch && fsPtr->cwdPtr != (Fs_Stream *)NIL) {
  1021.         *hdrPtrPtr = fsPtr->cwdPtr->ioHandlePtr;
  1022.         nameInfoPtr = fsPtr->cwdPtr->nameInfoPtr;
  1023.         *rootIDPtr = nameInfoPtr->rootID;
  1024.         *lookupNamePtr = fileName;
  1025.         *domainTypePtr = nameInfoPtr->domainType;
  1026.         *prefixPtrPtr = nameInfoPtr->prefixPtr;
  1027.     } else {
  1028.         status = FS_FILE_NOT_FOUND;
  1029.     }
  1030.     } else {
  1031.     fs_Stats.prefix.absolute++;
  1032.     LIST_FORALL(prefixList, (List_Links *) prefixPtr) {
  1033.         if (strncmp(prefixPtr->prefix, fileName, prefixPtr->prefixLength)
  1034.                     == 0) {
  1035.         char    lastChar;
  1036.  
  1037.         if (!(flags & prefixPtr->flags)) {
  1038.             /*
  1039.              * Only hit on imported or exported prefixes, as requested.
  1040.              */
  1041.             continue;
  1042.         }
  1043.         lastChar = fileName[prefixPtr->prefixLength];
  1044.         if (exactMatch && lastChar != '\0') {
  1045.             /*
  1046.              * Need an exact match, but there is more filename left.
  1047.              */
  1048.             continue;
  1049.         } else if (wantLink && lastChar == '\0' &&
  1050.                 prefixPtr->prefixLength != 1) {
  1051.             /*
  1052.              * The opposite of exact match.  We skip an exact match
  1053.              * if we are trying to open a remote link.  This makes
  1054.              * lstat() behave the same on all remote links, whether
  1055.              * or not there is an installed prefix for the link.
  1056.              */
  1057.             continue;
  1058.         } else if ((prefixPtr->prefixLength == 1) ||
  1059.                (lastChar == '\0') || (lastChar == '/')) {
  1060.             /*
  1061.              * The prefix is "/", or the prefix matches up through
  1062.              * a complete pathname component.  This implies that
  1063.              * /spur is not a valid prefix of /spurios.
  1064.              */
  1065.             if (longestPrefixPtr == (Fsprefix *)NIL) {
  1066.             longestPrefixPtr = prefixPtr;
  1067.             } else if (longestPrefixPtr->prefixLength <
  1068.                    prefixPtr->prefixLength) {
  1069.             longestPrefixPtr = prefixPtr;
  1070.             }
  1071.         }
  1072.         }
  1073.     }
  1074.     if (longestPrefixPtr != (Fsprefix *)NIL) {
  1075.         if ((flags & FSPREFIX_EXPORTED) && (clientID >= 0) &&
  1076.         (! List_IsEmpty(&longestPrefixPtr->exportList))) {
  1077.         /*
  1078.          * Check the export list to see if the remote client has
  1079.          * access.  An empty export list implies everyone has access.
  1080.          */
  1081.         register FsprefixExport *exportPtr;
  1082.         status = FS_NO_ACCESS;
  1083.         LIST_FORALL(&longestPrefixPtr->exportList,
  1084.                 (List_Links *)exportPtr) {
  1085.             if (exportPtr->spriteID == clientID) {
  1086.             status = SUCCESS;
  1087.             break;
  1088.             }
  1089.         }
  1090.         }
  1091.         if (status == SUCCESS) {
  1092.         *hdrPtrPtr = longestPrefixPtr->hdrPtr;
  1093.         *domainTypePtr = longestPrefixPtr->domainType;
  1094.         if (*hdrPtrPtr == (Fs_HandleHeader *)NIL) {
  1095.             /*
  1096.              * Return our caller the prefix instead of a relative name
  1097.              * so it can broadcast to get the prefix's handle.  If
  1098.              * the prefix has been installed under a specific serverID
  1099.              * then we return that so internet RPC (presumably) can
  1100.              * be used to contact the server.  Otherwise we'll
  1101.              * broadcast to locate the server.
  1102.              */
  1103.             *lookupNamePtr = longestPrefixPtr->prefix;
  1104.             if (longestPrefixPtr->flags & FSPREFIX_REMOTE) {
  1105.             *serverIDPtr = longestPrefixPtr->serverID;
  1106.             } else {
  1107.             *serverIDPtr = RPC_BROADCAST_SERVER_ID;
  1108.             }
  1109.             *prefixPtrPtr = (Fsprefix *)NIL;
  1110.             status = FS_NO_HANDLE;
  1111.         } else {
  1112.             /*
  1113.              * All set, return our caller the name after the prefix.
  1114.              * A name not starting with a slash is returned as the
  1115.              * relative name.  This is because of domains that
  1116.              * think that a name starting with a slash is absolute.
  1117.              */
  1118.             *rootIDPtr = (*hdrPtrPtr)->fileID;
  1119.             *lookupNamePtr = &fileName[longestPrefixPtr->prefixLength];
  1120.             while (**lookupNamePtr == '/') {
  1121.             (*lookupNamePtr)++;
  1122.             }
  1123.             *prefixPtrPtr = longestPrefixPtr;
  1124.         }
  1125.         }
  1126.     } else {
  1127.         status = FS_FILE_NOT_FOUND;
  1128.     }
  1129.     }
  1130. #ifdef SOSP91
  1131.     if (status==SUCCESS) {
  1132.     register char *ptr;
  1133.     register int nameComponent, restComponent;
  1134.     SOSPLookupNum++;
  1135.     nameComponent = 1; /* Components in incoming path. */
  1136.     for (ptr = fileName+1;*ptr != '\0';ptr++) {
  1137.         if (*ptr=='/') {
  1138.         nameComponent++;
  1139.         }
  1140.     }
  1141.     restComponent = 1; /* Components in returned path. */
  1142.     for (ptr = *lookupNamePtr;*ptr != '\0';ptr++) {
  1143.         if (*ptr=='/') {
  1144.         restComponent++;
  1145.         }
  1146.     }
  1147.     SOSPLookupPrefixComponent += nameComponent-restComponent;
  1148.     SOSPLookupComponent += nameComponent;
  1149.     }
  1150. #endif
  1151.     UNLOCK_MONITOR;
  1152.     return(status);
  1153. }
  1154.  
  1155. /*
  1156.  *----------------------------------------------------------------------
  1157.  *
  1158.  * Fsprefix_Export --
  1159.  *
  1160.  *    Add (or subtract) a client from the export list associated with
  1161.  *    a prefix.
  1162.  *
  1163.  * Results:
  1164.  *    None.
  1165.  *
  1166.  * Side effects:
  1167.  *    Update the export list of the prefix.
  1168.  *
  1169.  *----------------------------------------------------------------------
  1170.  */
  1171. ENTRY void
  1172. Fsprefix_Export(prefix, clientID, delete)
  1173.     char *prefix;        /* Update this prefix'es export list */
  1174.     int clientID;        /* Host ID of client to which to export */
  1175.     Boolean delete;        /* If TRUE, remove the client */
  1176. {
  1177.     register Fsprefix *prefixPtr;
  1178.     register FsprefixExport *exportPtr;
  1179.     Boolean found = FALSE;
  1180.  
  1181.     LOCK_MONITOR;
  1182.  
  1183.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1184.     if (strcmp(prefixPtr->prefix, prefix) == 0) {
  1185.         LIST_FORALL(&prefixPtr->exportList, (List_Links *)exportPtr) {
  1186.         if (exportPtr->spriteID == clientID) {
  1187.             if (delete) {
  1188.             List_Remove((List_Links *)exportPtr);
  1189.             free((Address)exportPtr);
  1190.             }
  1191.             found = TRUE;
  1192.             break;
  1193.         }
  1194.         }
  1195.         if (!found && !delete) {
  1196.         exportPtr = mnew(FsprefixExport);
  1197.         List_InitElement((List_Links *)exportPtr);
  1198.         exportPtr->spriteID = clientID;
  1199.         List_Insert((List_Links *)exportPtr,
  1200.                 LIST_ATREAR(&prefixPtr->exportList));
  1201.         }
  1202.         break;
  1203.     }
  1204.     }
  1205.     UNLOCK_MONITOR;
  1206. }
  1207.  
  1208. /*
  1209.  *----------------------------------------------------------------------
  1210.  *
  1211.  * Fsprefix_Clear --
  1212.  *
  1213.  *    Clear a prefix table entry.  If the deleteFlag argument is set
  1214.  *    then the entry is removed altogether, otherwise just the
  1215.  *    handle is closed and then cleared.  This is called from Fs_Command
  1216.  *    and used during testing.  This won't delete the root prefix,
  1217.  *    although it will clear its handle so subsequent lookups will
  1218.  *    rebroadcast.
  1219.  *
  1220.  * Results:
  1221.  *    None.
  1222.  *
  1223.  * Side effects:
  1224.  *    Delete a prefix or just clear its handle.
  1225.  *
  1226.  *----------------------------------------------------------------------
  1227.  */
  1228. ENTRY Boolean
  1229. Fsprefix_Clear(prefix, deleteFlag, forced)
  1230.     char *prefix;        /* String to install as a prefix */
  1231.     int deleteFlag;        /* If TRUE then the prefix is removed from
  1232.                  * the table.  Otherwise just the handle
  1233.                  * information is cleared. */
  1234.     Boolean forced;        /* If true, then this command is being forced
  1235.                  * from user-level.
  1236.                  */
  1237. {
  1238.     register Fsprefix *prefixPtr;
  1239.     Fsprefix *targetPrefixPtr = (Fsprefix *)NIL;
  1240.     Fs_FileID prefixID;
  1241.     Boolean okToNuke = TRUE;
  1242.  
  1243.     LOCK_MONITOR;
  1244.  
  1245.     /*
  1246.      * First pass to scan the table for the prefix and get the
  1247.      * flags and fileID associated with the prefix table entry.
  1248.      */
  1249.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1250.     if (strcmp(prefixPtr->prefix, prefix) == 0) {
  1251.         if (prefixPtr->flags & (FSPREFIX_EXPORTED|FSPREFIX_LOCAL)) {
  1252.         /*
  1253.          * We export the prefix and have to be careful about
  1254.          * deleting the prefix table entry for it.  Only if
  1255.          * there is another prefix corresponding to the same
  1256.          * domain can we delete this one.  This situation occurs
  1257.          * during bootstrap where "/bootTmp" is aliased to "/"
  1258.          * but eventually we want to nuke the local "/" so
  1259.          * we can hook up to the network "/".
  1260.          */
  1261.         if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  1262.             prefixID = prefixPtr->hdrPtr->fileID;
  1263.             okToNuke = FALSE;
  1264.         }
  1265.         }
  1266.         targetPrefixPtr = prefixPtr;
  1267.         break;
  1268.     }
  1269.     }
  1270.     /*
  1271.      * Second pass to look for an alias prefix.
  1272.      */
  1273.     if (!okToNuke) {
  1274.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1275.         if (strcmp(prefixPtr->prefix, prefix) != 0) {
  1276.         if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  1277.             register Fs_HandleHeader *hdrPtr = prefixPtr->hdrPtr;
  1278.             if (prefixID.type != hdrPtr->fileID.type ||
  1279.             prefixID.serverID != hdrPtr->fileID.serverID ||
  1280.             prefixID.major != hdrPtr->fileID.major ||
  1281.             prefixID.minor != hdrPtr->fileID.minor) {
  1282.             continue;
  1283.             }
  1284.             /*
  1285.              * Found an alias.
  1286.              */
  1287.             goto nukeIt;
  1288.         }
  1289.         }
  1290.     }
  1291.     /*
  1292.      * No other alias
  1293.      */
  1294.     UNLOCK_MONITOR;
  1295.     return(FAILURE);
  1296.     }
  1297. nukeIt:
  1298.     if (targetPrefixPtr == (Fsprefix *)NIL) {
  1299.     /*
  1300.      * No prefix match.
  1301.      */
  1302.     UNLOCK_MONITOR;
  1303.     return(FAILURE);
  1304.     } else {
  1305.     /*
  1306.      * Was this a force-loaded prefix?  We can only delete it if this
  1307.      * command is also being forced from user level.
  1308.      */
  1309.     if ((targetPrefixPtr->flags & FSPREFIX_FORCED) && !forced) {
  1310.         return FAILURE; 
  1311.     }
  1312.     if (targetPrefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  1313.         FsprefixHandleCloseInt(targetPrefixPtr, FSPREFIX_ANY);
  1314.     }
  1315.     targetPrefixPtr->serverID = RPC_BROADCAST_SERVER_ID;
  1316.     targetPrefixPtr->flags &= ~(FSPREFIX_EXPORTED|FSPREFIX_LOCAL);
  1317.     if (deleteFlag && targetPrefixPtr->prefixLength != 1) {
  1318.         free((Address) targetPrefixPtr->prefix);
  1319.         while (! List_IsEmpty(&targetPrefixPtr->exportList)) {
  1320.         register FsprefixExport *exportPtr;
  1321.         exportPtr =
  1322.             (FsprefixExport *)List_First(&targetPrefixPtr->exportList);
  1323.         List_Remove((List_Links *)exportPtr);
  1324.         free((Address)exportPtr);
  1325.         }
  1326.     
  1327.         List_Remove((List_Links *)targetPrefixPtr);
  1328.         free((Address) targetPrefixPtr);
  1329.     }
  1330.     UNLOCK_MONITOR;
  1331.     return(SUCCESS);
  1332.     }
  1333. }
  1334.  
  1335. /*
  1336.  *----------------------------------------------------------------------
  1337.  *
  1338.  * Fsprefix_HandleClose --
  1339.  *
  1340.  *    Close the handle associated with a prefix.  This is called when
  1341.  *    cleaning up a prefix table entry.  The flags argument indicates
  1342.  *    what sort of prefix we export to nuke, and this is used for
  1343.  *    consistency checking.
  1344.  *
  1345.  * Results:
  1346.  *    None.
  1347.  *
  1348.  * Side effects:
  1349.  *    None here, see the internal routine called inside the monitor lock.
  1350.  *
  1351.  *----------------------------------------------------------------------
  1352.  */
  1353. void
  1354. Fsprefix_HandleClose(prefixPtr, flags)
  1355.     Fsprefix *prefixPtr;
  1356.     int flags;            /* FSPREFIX_ANY, FSPREFIX_EXPORTED */
  1357. {
  1358.     LOCK_MONITOR;
  1359.     FsprefixHandleCloseInt(prefixPtr, flags);
  1360.     UNLOCK_MONITOR;
  1361. }
  1362.  
  1363. /*
  1364.  *----------------------------------------------------------------------
  1365.  *
  1366.  * FsprefixHandleCloseInt --
  1367.  *
  1368.  *    Close the handle associated with a prefix.  The serverID from
  1369.  *    the handle is saved for use in recovery later.
  1370.  *
  1371.  * Results:
  1372.  *    None.
  1373.  *
  1374.  * Side effects:
  1375.  *    Sets the prefix's hdrPtr to NIL.  This notifies the okToRecover
  1376.  *    condition if there were active opens on the prefix so that
  1377.  *    recovery can proceed on this very handle.
  1378.  *
  1379.  *----------------------------------------------------------------------
  1380.  */
  1381. void
  1382. FsprefixHandleCloseInt(prefixPtr, flags)
  1383.     Fsprefix *prefixPtr;
  1384.     int flags;
  1385. {
  1386.     register Fs_HandleHeader *hdrPtr;
  1387.     Fs_Stream dummy;
  1388.  
  1389.     if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  1390.     if ((flags & FSPREFIX_IMPORTED) &&
  1391.         (prefixPtr->flags & (FSPREFIX_EXPORTED|FSPREFIX_LOCAL))) {
  1392.         printf("Fsprefix_HandleClose: \"%s\" is exported (mounted)\n",
  1393.             prefixPtr->prefix);
  1394.         return;
  1395.     } else if ((flags & FSPREFIX_EXPORTED) &&
  1396.         (prefixPtr->flags & (FSPREFIX_EXPORTED|FSPREFIX_LOCAL) == 0)){
  1397.         printf("Fsprefix_HandleClose: \"%s\" is not exported (mounted)\n",
  1398.             prefixPtr->prefix);
  1399.         return;
  1400.     }
  1401.     if (prefixPtr->prefix != (char *) NIL) {
  1402.         printf("Fsprefix_HandleClose deleting \"%s\"\n", prefixPtr->prefix);
  1403.     }
  1404.     hdrPtr = prefixPtr->hdrPtr;
  1405.     prefixPtr->hdrPtr = (Fs_HandleHeader *)NIL;
  1406.     Fsutil_HandleLock(hdrPtr);
  1407.     dummy.ioHandlePtr = hdrPtr;
  1408.     dummy.hdr.fileID.type = -1;
  1409. #ifdef SOSP91
  1410.     (void)(*fsio_StreamOpTable[hdrPtr->fileID.type].close)(&dummy,
  1411.             rpc_SpriteID, 0, 0, 0, (ClientData)NIL, (int *) NIL,
  1412.             (int *) NIL);
  1413. #else
  1414.     (void)(*fsio_StreamOpTable[hdrPtr->fileID.type].close)(&dummy,
  1415.             rpc_SpriteID, 0, 0, 0, (ClientData)NIL);
  1416. #endif
  1417. #ifdef lint
  1418.     (void) Fsio_FileClose(&dummy, rpc_SpriteID, 0,
  1419.             0, 0, (ClientData)NIL);
  1420.     (void) FsrmtFileClose(&dummy, rpc_SpriteID, 0,
  1421.             0, 0, (ClientData)NIL);
  1422.     (void) Fsio_PipeClose(&dummy, rpc_SpriteID, 0,
  1423.             0, 0, (ClientData)NIL);
  1424.     (void) Fsio_DeviceClose(&dummy, rpc_SpriteID, 0,
  1425.             0, 0, (ClientData)NIL);
  1426.     (void) Fsrmt_IOClose(&dummy, rpc_SpriteID, 0,
  1427.             0, 0, (ClientData)NIL);
  1428.     (void) FspdevControlClose(&dummy, rpc_SpriteID, 0,
  1429.             0, 0, (ClientData)NIL);
  1430.     (void) FspdevPseudoStreamClose(&dummy, rpc_SpriteID, 0,
  1431.             0, 0, (ClientData)NIL);
  1432.     (void) FspdevServerStreamClose(&dummy, rpc_SpriteID, 0,
  1433.             0, 0, (ClientData)NIL);
  1434. #endif /* lint */
  1435.  
  1436.     if (prefixPtr->activeOpens > 0) {
  1437.         prefixPtr->activeOpens = 0;
  1438.         Sync_Broadcast(&prefixPtr->okToRecover);
  1439.     }
  1440.     }
  1441. }
  1442.  
  1443. /*
  1444.  *----------------------------------------------------------------------
  1445.  *
  1446.  * LocatePrefix --
  1447.  *
  1448.  *    Call a domain specific routine to get the token for a prefix.
  1449.  *
  1450.  * Results:
  1451.  *    The token for the prefix table and a return code.
  1452.  *
  1453.  * Side effects:
  1454.  *    Those of the domain specific Prefix routine.
  1455.  *
  1456.  *----------------------------------------------------------------------
  1457.  */
  1458. static ReturnStatus
  1459. LocatePrefix(fileName, serverID, domainTypePtr, hdrPtrPtr)
  1460.     char    *fileName;    /* The prefix to find the server of */
  1461.     int        serverID;    /* Id of server for prefix. */
  1462.     int        *domainTypePtr;    /* In/Out the type of the domain.  If -1 on
  1463.                  * entry then all domain prefix routines
  1464.                  * are polled in order to find the domain.
  1465.                  * Set upon return to domain type for prefix */
  1466.     Fs_HandleHeader **hdrPtrPtr;    /* The handle that the domain prefix routine
  1467.                  * returns for the prefix */
  1468. {
  1469.     register ReturnStatus    status;
  1470.     register int        domainType;
  1471.     Fs_UserIDs            ids;
  1472.  
  1473.     Fs_SetIDs(Proc_GetEffectiveProc(), &ids);
  1474.     for (domainType = 0; domainType < FS_NUM_DOMAINS; domainType++) {
  1475.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_IMPORT])
  1476.             (fileName, serverID, &ids, domainTypePtr, hdrPtrPtr);
  1477. #ifdef lint
  1478.     status = FsrmtImport(fileName, serverID, &ids, domainTypePtr,
  1479.                 hdrPtrPtr);
  1480. #endif /* lint */
  1481.     if (status == SUCCESS) {
  1482.         return(FS_NEW_PREFIX);
  1483.     } else if (status == RPC_FS_NO_PREFIX) {
  1484.         /* Delete prefix.  This won't delete it if load was also forced. */
  1485.         (void) Fsprefix_Clear(fileName, FALSE, FALSE);
  1486.     }
  1487.     }
  1488.     return(FS_FILE_NOT_FOUND);
  1489. }
  1490.  
  1491.  
  1492. /*
  1493.  *----------------------------------------------------------------------
  1494.  *
  1495.  * GetPrefix --
  1496.  *
  1497.  *    A common loop to deal with prefixes that have no handle yet.
  1498.  *    This takes care of finding the handle for a prefix if needed.
  1499.  *
  1500.  * Results:
  1501.  *    The handle for the prefix of the file.
  1502.  *
  1503.  * Side effects:
  1504.  *    May call LocatePrefix and Fsprefix_Install.
  1505.  *
  1506.  *----------------------------------------------------------------------
  1507.  */
  1508. static ReturnStatus
  1509. GetPrefix(fileName, follow, hdrPtrPtr, rootIDPtr, lookupNamePtr, domainTypePtr,
  1510.         prefixPtrPtr)
  1511.     char     *fileName;        /* File name that needs to be 
  1512.                      * operated on */
  1513.     Boolean    follow;            /* TRUE means lookup will follow links.
  1514.                      * FALSE allows opening of links */
  1515.     Fs_HandleHeader **hdrPtrPtr;        /* Result, handle for the prefix */
  1516.     Fs_FileID    *rootIDPtr;        /* Result, ID of domain root */
  1517.     char     **lookupNamePtr;    /* Result, remaining pathname to 
  1518.                      * lookup */
  1519.     int     *domainTypePtr;        /* Result, domain type of the prefix */
  1520.     Fsprefix     **prefixPtrPtr;        /* Result, reference to prefix table */
  1521. {
  1522.     ReturnStatus status;
  1523.     register int flags = FSPREFIX_IMPORTED;
  1524.     int         serverID;
  1525. #ifdef SOSP91
  1526.     SOSP_IN_NAME_LOOKUP_FIELD = 2;
  1527. #endif
  1528.  
  1529.     if (!follow) {
  1530.     flags |= FSPREFIX_LINK_NOT_PREFIX;
  1531.     }
  1532.     do {
  1533.     if (fsprefix_FileNameTrace) {
  1534.         printf("Lookup: %s,", fileName);
  1535.     }
  1536.     status = Fsprefix_Lookup(fileName, flags, FS_LOCALHOST_ID, hdrPtrPtr,
  1537.             rootIDPtr, lookupNamePtr, &serverID, domainTypePtr, 
  1538.             prefixPtrPtr);
  1539.     if (status == FS_NO_HANDLE) {
  1540.         /*
  1541.          * The prefix exists but there is not a valid file handle for it.
  1542.          * Fsprefix_Lookup has returned us the prefix in lookupName.
  1543.          */
  1544.         /*
  1545.          * If the server is ourself then return.  The prefix has 
  1546.          * probably been installed because we are going to export it
  1547.          * later and we shouldn't bother broadcasting for
  1548.          * it now.
  1549.          */
  1550.         if (serverID == rpc_SpriteID) {
  1551. #ifdef SOSP91
  1552.         SOSP_IN_NAME_LOOKUP_FIELD = 0;
  1553. #endif
  1554.         return FAILURE;
  1555.         }
  1556.         if (serverID == RPC_BROADCAST_SERVER_ID) {
  1557.         printf("Broadcasting for server of \"%s\"\n", *lookupNamePtr);
  1558.         } else {
  1559.         printf("Contacting server %d for \"%s\" prefix\n", serverID,
  1560.             *lookupNamePtr);
  1561.         }
  1562.         status = LocatePrefix(*lookupNamePtr, serverID, domainTypePtr,
  1563.                             hdrPtrPtr);
  1564.         if (status == FS_NEW_PREFIX) {
  1565.         char hostname[128];
  1566.  
  1567.         fs_Stats.prefix.found++;
  1568.  
  1569.         Net_SpriteIDToName((*hdrPtrPtr)->fileID.serverID, 128, 
  1570.             hostname);
  1571.         if (hostname[0] != '\0') {
  1572.             printf("Importing \"%s\" from %s\n", *lookupNamePtr,
  1573.                 hostname);
  1574.         } else {
  1575.             printf("Importing \"%s\" from host #%d\n", *lookupNamePtr,
  1576.             (*hdrPtrPtr)->fileID.serverID);
  1577.         }
  1578.         (void)Fsprefix_Install(*lookupNamePtr, *hdrPtrPtr,*domainTypePtr,
  1579.                 FSPREFIX_IMPORTED);
  1580.         }
  1581.     }
  1582.     } while (status == FS_NEW_PREFIX);
  1583. #ifdef SOSP91
  1584.         SOSP_IN_NAME_LOOKUP_FIELD = 0;
  1585. #endif
  1586.     return(status);
  1587. }
  1588.  
  1589. /*
  1590.  *----------------------------------------------------------------------
  1591.  *
  1592.  * Fsprefix_Reopen --
  1593.  *
  1594.  *    This is called to enter the re-open phase of recovery.
  1595.  *    This finds prefix table entries that have been
  1596.  *    cleared out (because the server went away) and tries
  1597.  *    to re-establish these - the prefix token is needed when
  1598.  *    re-opening other handles..
  1599.  *
  1600.  * Results:
  1601.  *    None.
  1602.  *
  1603.  * Side effects:
  1604.  *    Retries nil'ed prefixes.
  1605.  *
  1606.  *----------------------------------------------------------------------
  1607.  */
  1608. ENTRY void
  1609. Fsprefix_Reopen(serverID)
  1610.     int serverID;        /* Server we are recovering with */
  1611. {
  1612.     Fsprefix *prefixPtr;
  1613.     ReturnStatus status;
  1614.     Fs_HandleHeader *hdrPtr;
  1615.     int domainType;
  1616.     List_Links nilPrefixList;
  1617.  
  1618.     GetNilPrefixes(&nilPrefixList);
  1619.     while (!List_IsEmpty(&nilPrefixList)) {
  1620.     prefixPtr = (Fsprefix *)List_First(&nilPrefixList);
  1621.     if (prefixPtr->serverID == serverID ||
  1622.         prefixPtr->serverID == RPC_BROADCAST_SERVER_ID) {
  1623.         /*
  1624.          * Attempt to re-establish the prefix table entry before
  1625.          * re-opening files under that prefix.  This is needed
  1626.          * because the prefix table slot is a point of synchronization
  1627.          * between opens and re-opens.
  1628.          */
  1629.         domainType = -1;
  1630.         status = LocatePrefix(prefixPtr->prefix, prefixPtr->serverID,
  1631.                 &domainType, &hdrPtr);
  1632.         if (status == FS_NEW_PREFIX) {
  1633.         (void)Fsprefix_Install(prefixPtr->prefix, hdrPtr, domainType,
  1634.                 FSPREFIX_IMPORTED);
  1635.         }
  1636.     }
  1637.     List_Remove((List_Links *)prefixPtr);
  1638.     free(prefixPtr->prefix);
  1639.     free((Address)prefixPtr);
  1640.     }
  1641. }
  1642.  
  1643. /*
  1644.  *----------------------------------------------------------------------
  1645.  *
  1646.  * GetNilPrefixes --
  1647.  *
  1648.  *    Return a list of prefixes that have lost their handles.
  1649.  *
  1650.  * Results:
  1651.  *    None.
  1652.  *
  1653.  * Side effects:
  1654.  *    mallocs, our caller should free each element in the list.
  1655.  *
  1656.  *----------------------------------------------------------------------
  1657.  */
  1658. ENTRY static void
  1659. GetNilPrefixes(listPtr)
  1660.     List_Links *listPtr;    /* Header for list of prefix table entries */
  1661. {
  1662.     Fsprefix *prefixPtr;
  1663.  
  1664.     LOCK_MONITOR;
  1665.  
  1666.     List_Init(listPtr);
  1667.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1668.     if (prefixPtr->hdrPtr == (Fs_HandleHeader *)NIL) {
  1669.         register Fsprefix *newPrefixPtr;
  1670.  
  1671.         newPrefixPtr = mnew(Fsprefix);
  1672.         *newPrefixPtr = *prefixPtr;
  1673.         newPrefixPtr->prefix = (Address)malloc(newPrefixPtr->prefixLength + 1);
  1674.         (void)strcpy(newPrefixPtr->prefix, prefixPtr->prefix);
  1675.         List_Insert((List_Links *)newPrefixPtr, LIST_ATREAR(listPtr));
  1676.     }
  1677.     }
  1678.  
  1679.     UNLOCK_MONITOR;
  1680. }
  1681.  
  1682. /*
  1683.  *----------------------------------------------------------------------
  1684.  *
  1685.  * Fsprefix_OpenCheck --
  1686.  *
  1687.  *    This is called to indicate that an open is occurring in
  1688.  *    this domain.  This will fail if recovery is in progress
  1689.  *    with the server.
  1690.  *
  1691.  * Results:
  1692.  *    FS_DOMAIN_UNAVAILABLE if the prefix is locked up because recovery
  1693.  *    actions are in progress.
  1694.  *
  1695.  * Side effects:
  1696.  *    Blocks recovery until
  1697.  *    Fsprefix_OpenDone is called.
  1698.  *
  1699.  *----------------------------------------------------------------------
  1700.  */
  1701. ENTRY ReturnStatus
  1702. Fsprefix_OpenCheck(prefixHdrPtr)
  1703.     Fs_HandleHeader *prefixHdrPtr;    /* Handle from the prefix table */
  1704. {
  1705.     register ReturnStatus status;
  1706.     Fsprefix *prefixPtr;
  1707.     LOCK_MONITOR;
  1708.  
  1709.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1710.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1711.         (prefixPtr->hdrPtr->fileID.serverID ==
  1712.         prefixHdrPtr->fileID.serverID)) {
  1713.         if (prefixPtr->delayOpens) {
  1714.         printf( 
  1715.             "Fsprefix_OpenCheck waiting for recovery\n");
  1716.         if (Sync_Wait(&prefixPtr->okToOpen, TRUE)) {
  1717.             /*
  1718.              * Wait was interrupted by a signal.
  1719.              */
  1720.             status = FS_DOMAIN_UNAVAILABLE;
  1721.             printf("Fsprefix_OpenCheck aborted\n");
  1722.         } else {
  1723.             prefixPtr->activeOpens++;
  1724.             status = SUCCESS;
  1725.             printf("Fsprefix_OpenCheck ok\n");
  1726.         }
  1727.         } else {
  1728.         prefixPtr->activeOpens++;
  1729.         status = SUCCESS;
  1730.         }
  1731.         UNLOCK_MONITOR;
  1732.         return(status);
  1733.     }
  1734.     }
  1735.     /*
  1736.      * No match with the prefix handle.
  1737.      */
  1738.     printf( "PrefixOpenCheck: didn't find prefix");
  1739.     UNLOCK_MONITOR;
  1740.     return(FS_DOMAIN_UNAVAILABLE);
  1741. }
  1742.  
  1743. /*
  1744.  *----------------------------------------------------------------------
  1745.  *
  1746.  * Fsprefix_OpenDone --
  1747.  *
  1748.  *    The complement of FsPrefixOpenStart, this takes away the
  1749.  *    open reference count on the prefix and notifies any
  1750.  *    waiting recovery processes.
  1751.  *
  1752.  * Results:
  1753.  *    None.
  1754.  *
  1755.  * Side effects:
  1756.  *    Notifies the prefix okToRecover condition if activeOpens is zero.
  1757.  *
  1758.  *----------------------------------------------------------------------
  1759.  */
  1760. ENTRY void
  1761. Fsprefix_OpenDone(prefixHdrPtr)
  1762.     Fs_HandleHeader *prefixHdrPtr;    /* Handle from the prefix table */
  1763. {
  1764.     Fsprefix *prefixPtr;
  1765.     LOCK_MONITOR;
  1766.  
  1767.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1768.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1769.         (prefixPtr->hdrPtr->fileID.serverID ==
  1770.         prefixHdrPtr->fileID.serverID)) {
  1771.         prefixPtr->activeOpens--;
  1772.         if (prefixPtr->activeOpens < 0) {
  1773.         printf( "Fsprefix_OpenDone, neg open cnt\n");
  1774.         prefixPtr->activeOpens = 0;
  1775.         }
  1776.         if (prefixPtr->activeOpens == 0) {
  1777.         Sync_Broadcast(&prefixPtr->okToRecover);
  1778.         }
  1779.         UNLOCK_MONITOR;
  1780.         return;
  1781.     }
  1782.     }
  1783.     /*
  1784.      * No match with the prefix handle.
  1785.      */
  1786.     printf( "PrefixOpenDone: no handle match\n");
  1787.     UNLOCK_MONITOR;
  1788.     return;
  1789. }
  1790.  
  1791. /*
  1792.  *----------------------------------------------------------------------
  1793.  *
  1794.  * Fsprefix_RecoveryCheck --
  1795.  *
  1796.  *    This is called to indicate that we want to recover handles with
  1797.  *    this server.  This will block the calling process until any
  1798.  *    outstanding opens are completed so that opens and re-opens don't race.
  1799.  *
  1800.  * Results:
  1801.  *    None.
  1802.  *
  1803.  * Side effects:
  1804.  *    Blocks recovery until Fsprefix_OpenDone is called.
  1805.  *
  1806.  *----------------------------------------------------------------------
  1807.  */
  1808. ENTRY void
  1809. Fsprefix_RecoveryCheck(serverID)
  1810.     int serverID;
  1811. {
  1812.     Fsprefix *prefixPtr;
  1813.     LOCK_MONITOR;
  1814.  
  1815.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1816.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1817.         (prefixPtr->hdrPtr->fileID.serverID == serverID)) {
  1818.         while (prefixPtr->activeOpens > 0) {
  1819.         (void)Sync_Wait(&prefixPtr->okToRecover, FALSE);
  1820.         }
  1821.         prefixPtr->delayOpens = TRUE;
  1822.         UNLOCK_MONITOR;
  1823.         return;
  1824.     }
  1825.     }
  1826.     /*
  1827.      * No match with the prefix handle means the other host isn't a server.
  1828.      * There is no possibility of opens to race with re-opens.  We will
  1829.      * still need to re-open handles, however, because of remote devices.
  1830.      */
  1831.     UNLOCK_MONITOR;
  1832. }
  1833.  
  1834. /*
  1835.  *----------------------------------------------------------------------
  1836.  *
  1837.  * Fsprefix_AllowOpens --
  1838.  *
  1839.  *    As part of recovery, regular opens to a server are blocked
  1840.  *    until all the re-opens have been done.  This procedure indicates
  1841.  *    that the re-open phase is done and regular opens can proceed.
  1842.  *
  1843.  * Results:
  1844.  *    None.
  1845.  *
  1846.  * Side effects:
  1847.  *    Notifies the prefix okToOpen condition and clears the
  1848.  *    delayOpens boolean.
  1849.  *
  1850.  *----------------------------------------------------------------------
  1851.  */
  1852. ENTRY void
  1853. Fsprefix_AllowOpens(serverID)
  1854.     int serverID;        /* Server we are recovering with */
  1855. {
  1856.     Fsprefix *prefixPtr;
  1857.  
  1858.     LOCK_MONITOR;
  1859.  
  1860.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1861.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1862.         (prefixPtr->hdrPtr->fileID.serverID == serverID)) {
  1863.         prefixPtr->delayOpens = FALSE;
  1864.         Sync_Broadcast(&prefixPtr->okToOpen);
  1865.     }
  1866.     }
  1867.     UNLOCK_MONITOR;
  1868.     return;
  1869. }
  1870.  
  1871. /*
  1872.  *----------------------------------------------------------------------
  1873.  *
  1874.  * Fsprefix_FromFileID --
  1875.  *
  1876.  *    Return the prefix table entry given the fileID for the prefix.
  1877.  *    This reverse mapping is needed during recovery in order to
  1878.  *    re-establish the back pointer from a handle to the prefix
  1879.  *    table entry.  This in turn is used in ".." processing.
  1880.  *
  1881.  * Results:
  1882.  *    A pointer to the prefix table for the prefix rooted at
  1883.  *    the input fileID, or NIL if not found.
  1884.  *
  1885.  * Side effects:
  1886.  *    None.
  1887.  *
  1888.  *----------------------------------------------------------------------
  1889.  */
  1890. ENTRY Fsprefix *
  1891. Fsprefix_FromFileID(fileIDPtr)
  1892.     Fs_FileID    *fileIDPtr;        /* FileID from a client */
  1893. {
  1894.     Fsprefix *prefixPtr;
  1895.     LOCK_MONITOR;
  1896.  
  1897.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1898.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1899.         (prefixPtr->hdrPtr->fileID.serverID ==
  1900.         fileIDPtr->serverID) &&
  1901.         (prefixPtr->hdrPtr->fileID.major ==    fileIDPtr->major) &&
  1902.         (prefixPtr->hdrPtr->fileID.minor ==    fileIDPtr->minor)) {
  1903.         UNLOCK_MONITOR;
  1904.         return(prefixPtr);
  1905.     }
  1906.     }
  1907.     /*
  1908.      * No match with the fileID.
  1909.      */
  1910.     UNLOCK_MONITOR;
  1911.     return((Fsprefix *)NIL);
  1912. }
  1913.  
  1914. /*
  1915.  *----------------------------------------------------------------------
  1916.  *
  1917.  * Fsprefix_OpenInProgress --
  1918.  *
  1919.  *    This is called to find out if opens are in progress in
  1920.  *    a particular domain.  This is used by the cache consistency
  1921.  *    routines to decide if a consistency message might apply
  1922.  *    to an open hasn't quite completed.
  1923.  *
  1924.  * Results:
  1925.  *    None.
  1926.  *
  1927.  * Side effects:
  1928.  *    Blocks recovery until
  1929.  *    Fsprefix_OpenDone is called.
  1930.  *
  1931.  *----------------------------------------------------------------------
  1932.  */
  1933. ENTRY int
  1934. Fsprefix_OpenInProgress(fileIDPtr)
  1935.     Fs_FileID *fileIDPtr;        /* ID for some file */
  1936. {
  1937.     int activeOpens;
  1938.     Fsprefix *prefixPtr;
  1939.     LOCK_MONITOR;
  1940.  
  1941.     LIST_FORALL(prefixList, (List_Links *)prefixPtr) {
  1942.     if ((prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) &&
  1943.         (prefixPtr->hdrPtr->fileID.serverID == fileIDPtr->serverID) &&
  1944.         (prefixPtr->hdrPtr->fileID.major ==    fileIDPtr->major)) {
  1945.         activeOpens = prefixPtr->activeOpens;
  1946.         UNLOCK_MONITOR;
  1947.         return(activeOpens);
  1948.     }
  1949.     }
  1950.     /*
  1951.      * No match with any prefix, must not be any active opens.
  1952.      */
  1953.     UNLOCK_MONITOR;
  1954.     return(0);
  1955. }
  1956.  
  1957. /*
  1958.  *----------------------------------------------------------------------
  1959.  *
  1960.  * FsPrefixInterate --
  1961.  *
  1962.  *    This is called to loop through the prefix table entries.
  1963.  *    Our caller is given 'read-only' access to the prefix table
  1964.  *    entry.  This is used for the 'df' and 'prefix' programs
  1965.  *    which call Fsprefix_Dump.
  1966.  *    
  1967.  *    Upon entry, the *prefixPtr should be NIL to indicate the
  1968.  *    beginning of the iteration.
  1969.  *
  1970.  * Results:
  1971.  *    A pointer to the next prefix table entry.
  1972.  *
  1973.  * Side effects:
  1974.  *    Marks the next prefix table entry as non-deletable, and
  1975.  *    returns a pointer to it.
  1976.  *
  1977.  *----------------------------------------------------------------------
  1978.  */
  1979. ENTRY void
  1980. FsprefixIterate(prefixPtrPtr)
  1981.     Fsprefix **prefixPtrPtr;        /* In/Out pointer to prefix entry */
  1982. {
  1983.     register Fsprefix *prefixPtr;
  1984.     LOCK_MONITOR;
  1985.  
  1986.     prefixPtr = *prefixPtrPtr;
  1987.     if (prefixPtr == (Fsprefix *)NIL) {
  1988.     prefixPtr = (Fsprefix *)List_First(prefixList);
  1989.     } else {
  1990.     prefixPtr->flags &= ~FSPREFIX_LOCKED;
  1991.     prefixPtr = (Fsprefix *)List_Next(((List_Links *)prefixPtr));
  1992.     if (List_IsAtEnd(prefixList, (List_Links *)prefixPtr)) {
  1993.         prefixPtr = (Fsprefix *)NIL;
  1994.     }
  1995.     }
  1996.     if (prefixPtr != (Fsprefix *)NIL) {
  1997.     prefixPtr->flags |= FSPREFIX_LOCKED;
  1998.     }
  1999.     *prefixPtrPtr = prefixPtr;
  2000.     UNLOCK_MONITOR;
  2001. }
  2002.  
  2003. /*
  2004.  *----------------------------------------------------------------------
  2005.  *
  2006.  * FsprefixDone --
  2007.  *
  2008.  *    This is called to terminate a prefix table iteration.  The
  2009.  *    current entry is unlocked so it could be deleted.
  2010.  *
  2011.  * Results:
  2012.  *    None.
  2013.  *
  2014.  * Side effects:
  2015.  *    Clears the FSPREFIX_LOCKED bit in the prefix table entry.
  2016.  *
  2017.  *----------------------------------------------------------------------
  2018.  */
  2019. ENTRY void
  2020. FsprefixDone(prefixPtr)
  2021.     Fsprefix *prefixPtr;
  2022. {
  2023.     LOCK_MONITOR;
  2024.  
  2025.     if (prefixPtr != (Fsprefix *)NIL) {
  2026.     prefixPtr->flags &= ~FSPREFIX_LOCKED;
  2027.     }
  2028.     UNLOCK_MONITOR;
  2029. }
  2030.  
  2031. /*
  2032.  *----------------------------------------------------------------------
  2033.  *
  2034.  * Fsprefix_Dump --
  2035.  *
  2036.  *    Dump out the prefix table to the console, or copy individual
  2037.  *    elements out to user space.
  2038.  *
  2039.  * Results:
  2040.  *    None.
  2041.  *
  2042.  * Side effects:
  2043.  *    Console prints.
  2044.  *
  2045.  *----------------------------------------------------------------------
  2046.  */
  2047.  
  2048. ReturnStatus
  2049. Fsprefix_Dump(index, argPtr)
  2050.     int index;        /* Prefix table index, -1 means dump to console */
  2051.     Address argPtr;    /* Buffer space for entry */
  2052. {
  2053.     Fsprefix *prefixPtr;        /* Pointer to table entry */
  2054.     Boolean    foundPrefix = FALSE;
  2055.     int i;
  2056.  
  2057.     i = 0;
  2058.     prefixPtr = (Fsprefix *)NIL;
  2059.     FsprefixIterate(&prefixPtr);
  2060.     while (prefixPtr != (Fsprefix *)NIL) {
  2061.     if (index < 0) {
  2062.         /*
  2063.          * Dump the prefix entry to the console.
  2064.          */
  2065.         printf("%-20s ", prefixPtr->prefix);
  2066.         if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  2067.         printf("(%d,%d,%d,%x) ",
  2068.                   prefixPtr->hdrPtr->fileID.serverID,
  2069.                   prefixPtr->hdrPtr->fileID.type,
  2070.                   prefixPtr->hdrPtr->fileID.major,
  2071.                   prefixPtr->hdrPtr->fileID.minor);
  2072.         } else {
  2073.         printf(" (no handle) ");
  2074.         }
  2075.         if (prefixPtr->flags & FSPREFIX_LOCAL) {
  2076.         printf(" import ");
  2077.         }
  2078.         if (prefixPtr->flags & FSPREFIX_IMPORTED) {
  2079.         printf(" import ");
  2080.         }
  2081.         if (prefixPtr->flags & FSPREFIX_EXPORTED) {
  2082.         printf(" export ");
  2083.         }
  2084.         printf("\n");
  2085.     } else if (i == index) {
  2086.         Fs_Prefix userPrefix;
  2087.         if (prefixPtr->hdrPtr != (Fs_HandleHeader *)NIL) {
  2088.         /*
  2089.          * Call down to a domain-specific routine to get the
  2090.          * information about the domain.  We pass in a copy
  2091.          * of the file ID here because pseudo-file-system's
  2092.          * will change the ID to match the user-visible one,
  2093.          * not the internal one we use in the kernel.
  2094.          */
  2095.         Fs_FileID fileID;
  2096.         register Fs_FileID *fileIDPtr = &fileID;
  2097.  
  2098.         *fileIDPtr = prefixPtr->hdrPtr->fileID;
  2099.         (void) Fsutil_DomainInfo(fileIDPtr, &userPrefix.domainInfo);
  2100.         userPrefix.serverID    = fileIDPtr->serverID;
  2101.         userPrefix.domain    = fileIDPtr->major;
  2102.         userPrefix.fileNumber    = fileIDPtr->minor;
  2103.         userPrefix.version    = fileIDPtr->type;
  2104.         } else {
  2105.         userPrefix.serverID    = RPC_BROADCAST_SERVER_ID;
  2106.         userPrefix.domain    = -1;
  2107.         userPrefix.fileNumber    = -1;
  2108.         userPrefix.version    = -1;
  2109.         userPrefix.domainInfo.maxKbytes = -1;
  2110.         userPrefix.domainInfo.freeKbytes = -1;
  2111.         userPrefix.domainInfo.maxFileDesc = -1;
  2112.         userPrefix.domainInfo.freeFileDesc = -1;
  2113.         userPrefix.domainInfo.blockSize = -1;
  2114.         userPrefix.domainInfo.optSize = -1;
  2115.         }
  2116.         userPrefix.flags = prefixPtr->flags & ~FSPREFIX_LOCKED;
  2117.         if (prefixPtr->prefixLength >= FS_USER_PREFIX_LENGTH) {
  2118.         bcopy((Address)prefixPtr->prefix, (Address)userPrefix.prefix, FS_USER_PREFIX_LENGTH);
  2119.         userPrefix.prefix[FS_USER_PREFIX_LENGTH-1] = '\0';
  2120.         } else {
  2121.         (void)strcpy(userPrefix.prefix, prefixPtr->prefix);
  2122.         }
  2123.         Vm_CopyOut(sizeof(Fs_Prefix), (Address)&userPrefix, argPtr);
  2124.         foundPrefix = TRUE;
  2125.     }
  2126.     i++;
  2127.     if (!foundPrefix) {
  2128.         FsprefixIterate(&prefixPtr);
  2129.     } else {
  2130.         FsprefixDone(prefixPtr);
  2131.         break;
  2132.     }
  2133.     }
  2134.     if (index < 0 || foundPrefix) {
  2135.     return(SUCCESS);
  2136.     } else {
  2137.     return(FS_INVALID_ARG);
  2138.     }
  2139. }
  2140.  
  2141. /*
  2142.  *----------------------------------------------------------------------
  2143.  *
  2144.  * Fsprefix_DumpExport --
  2145.  *
  2146.  *    Return the export list of a prefix to user space.  The input
  2147.  *    buffer contains a prefix upon entry, and we then overwrite
  2148.  *    that with an array of SpriteIDs that corresponds to the export list.
  2149.  *    The end of the list is indicated by a spriteID of zero.
  2150.  *
  2151.  * Results:
  2152.  *    SUCCESS.
  2153.  *
  2154.  * Side effects:
  2155.  *    Copies stuff out to user space.
  2156.  *
  2157.  *----------------------------------------------------------------------
  2158.  */
  2159.  
  2160. ReturnStatus
  2161. Fsprefix_DumpExport(size, buffer)
  2162.     int size;        /* Size of buffer in bytes */
  2163.     Address buffer;    /* Buffer space for prefix then export list */
  2164. {
  2165.     Fsprefix *prefixPtr;    /* Pointer to table entry */
  2166.     char     prefix[FS_MAX_NAME_LENGTH];
  2167.     Fs_HandleHeader *hdrPtr;
  2168.     Fs_FileID rootID;
  2169.     char *name;
  2170.     int domain;
  2171.     int length;
  2172.     int serverID;
  2173.     ReturnStatus status;
  2174.  
  2175.     if (Fsutil_StringNCopy(FS_MAX_NAME_LENGTH, buffer, prefix, &length) !=
  2176.         SUCCESS) {
  2177.     return(SYS_ARG_NOACCESS);
  2178.     } else if (length == FS_MAX_NAME_LENGTH) {
  2179.     return(FS_INVALID_ARG);
  2180.     }
  2181.     status = Fsprefix_Lookup(prefix, FSPREFIX_EXACT|FSPREFIX_EXPORTED, -1,
  2182.         &hdrPtr, &rootID, &name, &serverID, &domain, &prefixPtr);
  2183.     if (status == SUCCESS) {
  2184.     status = DumpExportList(prefixPtr, size, buffer);
  2185.     }
  2186.     return(status);
  2187. }
  2188.  
  2189. /*
  2190.  *----------------------------------------------------------------------
  2191.  *
  2192.  * DumpExportList --
  2193.  *
  2194.  *    A monitored routine to copy out the export list to user space.
  2195.  *
  2196.  * Results:
  2197.  *    SUCCESS.
  2198.  *
  2199.  * Side effects:
  2200.  *    Copies stuff out to user space.
  2201.  *
  2202.  *----------------------------------------------------------------------
  2203.  */
  2204.  
  2205. static ReturnStatus
  2206. DumpExportList(prefixPtr, size, buffer)
  2207.     Fsprefix *prefixPtr;
  2208.     int size;
  2209.     char *buffer;
  2210. {
  2211.     int *exportList;
  2212.     int *iPtr;
  2213.     ReturnStatus status;
  2214.     FsprefixExport *exportPtr;
  2215.  
  2216.     LOCK_MONITOR;
  2217.     if (size > 1000 * sizeof(int)) {
  2218.     status = FS_INVALID_ARG;
  2219.     } else {
  2220.     exportList = (int *)malloc(size);
  2221.     bzero((Address)exportList, size);
  2222.     iPtr = exportList;
  2223.     LIST_FORALL(&prefixPtr->exportList, (List_Links *)exportPtr) {
  2224.         *iPtr = exportPtr->spriteID;
  2225.         iPtr++;
  2226.     }
  2227.     status = Vm_CopyOut(size, (Address)exportList, (Address)buffer);
  2228.     }
  2229.     UNLOCK_MONITOR;
  2230.     return(status);
  2231. }
  2232.  
  2233.